{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Convolutional Neural Network\n",
    "\n",
    "### Convolutional Layers: [128,128] ; Dense Layers [128,128]\n",
    "### Activation function = ReLU; Weight initilizer = He\n",
    "\n",
    "CNN is trained on raw data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stored variables and their in-db values:\n",
      "X_test              -> defaultdict(<class 'list'>, {0: array([[[  2.23553\n",
      "X_train             -> array([[[ -1.49427662e-02,  -5.38582681e-03,   3.2\n",
      "snrs                -> [-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, \n",
      "y_test              -> defaultdict(<class 'list'>, {0: array([1, 4, 1, ..\n",
      "y_train             -> array([1, 5, 7, ..., 4, 3, 3])\n"
     ]
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from collections import defaultdict\n",
    "from time import time\n",
    "\n",
    "%store -r\n",
    "%store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training data:  (80000, 2, 128) and labels:  (80000,)\n",
      "\n",
      "Test data:\n",
      "Total 20 (4000, 2, 128) arrays for SNR values:\n",
      "[-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n"
     ]
    }
   ],
   "source": [
    "print(\"Training data: \", X_train.shape, \"and labels: \", y_train.shape)\n",
    "print()\n",
    "print(\"Test data:\")\n",
    "print(\"Total\", len(X_test), X_test[18].shape, \"arrays for SNR values:\")\n",
    "print(sorted(X_test.keys()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Standardize the features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (80000, 2, 128)\n",
      "Test set corresponding to one snr value (4000, 2, 128)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "sc = StandardScaler()\n",
    "_X_train = np.reshape(X_train, [X_train.shape[0], X_train.shape[1]*X_train.shape[2]])\n",
    "_X_train = sc.fit_transform(_X_train)\n",
    "\n",
    "X_train = np.reshape(_X_train, X_train.shape)\n",
    "print(\"Training set\", X_train.shape)\n",
    "\n",
    "_X_test = defaultdict(list)\n",
    "for snr in snrs:\n",
    "    _X_test[snr] = np.reshape(X_test[snr], [X_test[snr].shape[0], X_test[snr].shape[1]*X_test[snr].shape[2]])\n",
    "    _X_test[snr] = sc.transform(_X_test[snr])\n",
    "    X_test[snr] = np.reshape(_X_test[snr], X_test[snr].shape)\n",
    "    \n",
    "print(\"Test set corresponding to one snr value\", X_test[18].shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Design and train the CNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0 training accuracy : 0.2939453125\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 1 training accuracy : 0.3837890625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 2 training accuracy : 0.43359375\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 3 training accuracy : 0.5\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 4 training accuracy : 0.5634765625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 5 training accuracy : 0.59765625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 6 training accuracy : 0.6083984375\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 7 training accuracy : 0.6328125\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 8 training accuracy : 0.64453125\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Epoch 9 training accuracy : 0.6669921875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Training took 29.398084 minutes\n"
     ]
    }
   ],
   "source": [
    "height = 2\n",
    "width = 128\n",
    "channels = 1\n",
    "n_features = height * width\n",
    "\n",
    "feature_map1 = 128\n",
    "ksize_conv1 = 2\n",
    "stride_conv1 = 1\n",
    "\n",
    "feature_map2 = 128\n",
    "ksize_conv2 = 2\n",
    "stride_conv2 = 1\n",
    "\n",
    "pool_layer_maps = 128\n",
    "\n",
    "n_fully_conn1 = 128\n",
    "n_fully_conn2 = 128\n",
    "\n",
    "n_classes = 8\n",
    "  \n",
    "X = tf.placeholder(tf.float32, shape=[None, height, width])\n",
    "X_reshaped = tf.reshape(X, shape=[-1, height, width, channels])\n",
    "labels = tf.placeholder(tf.int32, shape=[None])\n",
    "\n",
    "weight_init = tf.contrib.layers.variance_scaling_initializer()\n",
    "activation_func = tf.nn.relu()\n",
    "\n",
    "# ------------------ Convolutional layers ----------------------------\n",
    "\n",
    "def convolutional_layer(X, filter_, ksize, kernel_init, strides, padding):\n",
    "    convolutional_layer = tf.layers.conv2d(X, filters = filter_, kernel_initializer = kernel_init,\n",
    "                                           kernel_size = ksize, strides = strides,\n",
    "                                          padding = padding, activation = activation_func)\n",
    "    return convolutional_layer\n",
    "\n",
    "conv_layer1 = convolutional_layer(X_reshaped, feature_map1, ksize_conv1, weight_init, stride_conv1, padding = \"SAME\")\n",
    "\n",
    "conv_layer2 = convolutional_layer(conv_layer1, feature_map2, ksize_conv2, weight_init, stride_conv2, padding = \"SAME\")\n",
    "\n",
    "# ----------------- Pooling layers -------------------------------------\n",
    "\n",
    "def pooling_layer(convlayer, ksize, strides, padding, pool_maps):\n",
    "    pool = tf.nn.max_pool(convlayer, ksize, strides, padding)\n",
    "    dim1, dim2 = int(pool.get_shape()[1]), int(pool.get_shape()[2])\n",
    "    pool_flat = tf.reshape(pool, shape = [-1, pool_maps * dim1 * dim2])\n",
    "    return pool_flat\n",
    "\n",
    "pool_layer_flat = pooling_layer(conv_layer2, [1,2,2,1], [1,2,2,1], \"VALID\", pool_layer_maps)\n",
    "\n",
    "# ----------------- Fully connected layers -------------------\n",
    "\n",
    "def dense_layer(input_layer, n_neurons, kernel_init, activation):\n",
    "    fully_conn = tf.layers.dense(inputs = input_layer, units = n_neurons, activation = activation,\n",
    "                                kernel_initializer = kernel_init)\n",
    "    return fully_conn\n",
    "        \n",
    "dense_layer1 = dense_layer(pool_layer_flat, n_fully_conn1, weight_init, activation_func)\n",
    "\n",
    "dense_layer2 = dense_layer(dense_layer1, n_fully_conn2, weight_init, activation_func)\n",
    "\n",
    "# ----------------- Output softmax layer ---------------------------\n",
    "\n",
    "logits = tf.layers.dense(dense_layer2, n_classes)\n",
    "softmax_activations = tf.nn.softmax(logits)\n",
    "\n",
    "# ----------------- Specify performance measure -------------------------------\n",
    "\n",
    "cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits = logits, labels = labels)\n",
    "loss = tf.reduce_mean(cross_entropy)\n",
    "optimizer = tf.train.AdamOptimizer()\n",
    "train_operation = optimizer.minimize(loss)\n",
    "\n",
    "correct_predictions = tf.nn.in_top_k(logits, labels, 1)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))\n",
    "\n",
    "# ---------------- Execution phase -------------------------------------------\n",
    "    \n",
    "n_epochs = 10\n",
    "batch_size = 1024\n",
    "n_train = X_train.shape[0]\n",
    "n_iter = n_train//batch_size\n",
    "\n",
    "acc_test = defaultdict(list)\n",
    "\n",
    "path = \"./CNN_relu_he\"  \n",
    "saver = tf.train.Saver()\n",
    "\n",
    "start = time()\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    tf.global_variables_initializer().run()\n",
    "    for epoch in range(n_epochs):\n",
    "        for iteration in range(n_iter):\n",
    "            rand_indices = np.random.choice(n_train,batch_size)    \n",
    "            X_batch, y_batch = X_train[rand_indices], y_train[rand_indices]\n",
    "            sess.run(train_operation, feed_dict={X: X_batch, labels: y_batch})\n",
    "        acc_train = accuracy.eval(feed_dict={X: X_batch, labels: y_batch})\n",
    "        print(\"Epoch {} training accuracy : {}\".format(epoch, acc_train))\n",
    "        save_path = saver.save(sess, path)\n",
    "        saver.restore(sess, path)\n",
    "    saver.restore(sess, path)\n",
    "    for snr in snrs:\n",
    "        acc_test[snr] = accuracy.eval(feed_dict={X: X_test[snr], labels: y_test[snr]})\n",
    "\n",
    "print(\"Training took %f minutes\"%(float(time() - start)/60.0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Test the classifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CNN's test accuracy on -20dB SNR samples = 0.1315000057220459\n",
      "CNN's test accuracy on -18dB SNR samples = 0.12300000339746475\n",
      "CNN's test accuracy on -16dB SNR samples = 0.12475000321865082\n",
      "CNN's test accuracy on -14dB SNR samples = 0.14274999499320984\n",
      "CNN's test accuracy on -12dB SNR samples = 0.16949999332427979\n",
      "CNN's test accuracy on -10dB SNR samples = 0.20024999976158142\n",
      "CNN's test accuracy on -8dB SNR samples = 0.26600000262260437\n",
      "CNN's test accuracy on -6dB SNR samples = 0.3557499945163727\n",
      "CNN's test accuracy on -4dB SNR samples = 0.4957500100135803\n",
      "CNN's test accuracy on -2dB SNR samples = 0.6499999761581421\n",
      "CNN's test accuracy on 0dB SNR samples = 0.7367500066757202\n",
      "CNN's test accuracy on 2dB SNR samples = 0.7887499928474426\n",
      "CNN's test accuracy on 4dB SNR samples = 0.8205000162124634\n",
      "CNN's test accuracy on 6dB SNR samples = 0.8102499842643738\n",
      "CNN's test accuracy on 8dB SNR samples = 0.8147500157356262\n",
      "CNN's test accuracy on 10dB SNR samples = 0.8182500004768372\n",
      "CNN's test accuracy on 12dB SNR samples = 0.8140000104904175\n",
      "CNN's test accuracy on 14dB SNR samples = 0.8050000071525574\n",
      "CNN's test accuracy on 16dB SNR samples = 0.8192499876022339\n",
      "CNN's test accuracy on 18dB SNR samples = 0.8177499771118164\n"
     ]
    }
   ],
   "source": [
    "for snr in snrs:\n",
    "    print(\"CNN's test accuracy on {}dB SNR samples = {}\".format(snr,acc_test[snr]))  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Visualize classifier's performance on test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f7123b4e898>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.style.use('classic')\n",
    "%matplotlib inline\n",
    "\n",
    "acc_test = sorted(acc_test.items())\n",
    "new_acc = []\n",
    "for i in range(len(acc_test)):\n",
    "    new_acc.append(acc_test[i][1])\n",
    "acc_test_values = new_acc \n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "x = snrs\n",
    "y = list(acc_test_values)\n",
    "plt.plot(x, y, marker=\"o\", linewidth=2.0, linestyle='dashed', color='royalblue')\n",
    "plt.axis([-20, 20, 0, 1])\n",
    "plt.xticks(np.arange(min(x), max(x)+1, 2.0))\n",
    "plt.yticks(np.arange(0, 1, 0.10))\n",
    "\n",
    "ttl = plt.title('SNR vs Accuracy', fontsize=16)\n",
    "ttl.set_weight('bold')\n",
    "plt.xlabel('SNR (dB)', fontsize=14)\n",
    "plt.ylabel('Test accuracy', fontsize=14)\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Restoring parameters from ./CNN_relu_he\n",
      "Confusion Matrix\n",
      "       8PSK  BPSK  CPFSK  GFSK  PAM4  QAM16  QAM64  QPSK\n",
      "8PSK   0.69  0.00   0.00  0.00  0.00   0.09   0.04  0.17\n",
      "BPSK   0.00  0.97   0.00  0.00  0.01   0.00   0.00  0.01\n",
      "CPFSK  0.02  0.00   0.97  0.00  0.00   0.00   0.00  0.01\n",
      "GFSK   0.01  0.00   0.01  0.97  0.00   0.00   0.00  0.00\n",
      "PAM4   0.00  0.01   0.00  0.00  0.99   0.00   0.00  0.00\n",
      "QAM16  0.02  0.00   0.00  0.00  0.00   0.50   0.47  0.01\n",
      "QAM64  0.02  0.00   0.00  0.00  0.00   0.42   0.55  0.01\n",
      "QPSK   0.07  0.01   0.00  0.00  0.00   0.01   0.00  0.92\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f712b310e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Confusion Matrix\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    Z = logits.eval(feed_dict = {X : X_test[18]})\n",
    "    predicted_18dB = np.argmax(Z, axis = 1)\n",
    "    \n",
    "from sklearn.metrics import confusion_matrix\n",
    "%matplotlib inline\n",
    "\n",
    "classes = ['8PSK', 'BPSK', 'CPFSK', 'GFSK', 'PAM4', 'QAM16', 'QAM64', 'QPSK']\n",
    "conf_matrix = confusion_matrix(predicted_18dB, y_test[18])  \n",
    "\n",
    "conf_matrix = conf_matrix.astype('float') / conf_matrix.sum(axis=1)[:, np.newaxis]\n",
    "conf_matrix = conf_matrix.round(decimals = 2)\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(data = conf_matrix, columns = classes, index = classes) \n",
    "print(\"Confusion Matrix\")\n",
    "print(df)\n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "plt.imshow(conf_matrix, interpolation = 'nearest', cmap = plt.cm.Purples)\n",
    "ticks = np.arange(len(classes))\n",
    "plt.title(\"Confusion Matrix\")\n",
    "plt.xticks(ticks, classes, rotation=45)\n",
    "plt.yticks(ticks, classes)\n",
    "\n",
    "plt.ylabel('True class')\n",
    "plt.xlabel('Predicted class')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.colorbar()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
